<?php

namespace App\Services\Product;

use App\Exceptions\UserException;
use App\Facades\UserManager;
use App\Facades\DeviceManager;
use App\Facades\WeChatService as WeChat;
use App\Models\RoleUser;
use Cache;
use Carbon\Carbon;
use DB;
use Exception;
use Sentinel;

class UserService 
{
	/**
     * 创建或更新用户微信账号信息
     * @param  string  $code        微信授权 code
     */
    public function add($code)
    {
        $oAuthAccessToken = WeChat::oAuthAccessToken($code);

        if ($oAuthAccessToken){
            $userInfo = WeChat::getUserInfo($oAuthAccessToken);
            
            Cache::put($userInfo['openid'].'userWxInfo', $userInfo, Carbon::now()->addMinutes(env('CACHE_USER_WX_INFO_TIME', 300)));
            
            $user = Sentinel::findByCredentials(['username' => $userInfo['openid']]);
            if(is_null($user)){
            	$user = Sentinel::registerAndActivate([
                    'username' => $userInfo['openid'],
                    'password' => 'password',
                ]);
            }
            Sentinel::login($user);
        }
	}

    /**
     * [updateUserInfo description]
     * @param  array $data 
     * @return        
     */
	public function updateUserInfo($data)
	{
		$user = UserManager::getUser();
		$userWxInfo = Cache::get($user->username.'userWxInfo');
		$userInfo = UserManager::getUserInfoBuilderByUsername($user->username)->get();
		try{
			if(count($userInfo)){
                if(!is_null($data)){
    				$data = array_merge($data, [
    		            'wx_nickname' => $userWxInfo['nickname'],
    		            'wx_head_img_url' => $userWxInfo['headimgurl'],
    		            'wx_sex' => $userWxInfo['sex'],
    		            'wx_city' => $userWxInfo['city'],
    		            'wx_province' => $userWxInfo['province'],
    		            'wx_country' => $userWxInfo['country'],
    					]);
                }
				UserManager::updateUserInfo($user->id, $data);
            }else{
                if(!is_null($data)){
                    $data = array_merge($data, [
                        'user_id' => $user->id,
                        'open_id' => $userWxInfo['openid'],
                        'wx_nickname' => $userWxInfo['nickname'],
                        'wx_head_img_url' => $userWxInfo['headimgurl'],
                        'wx_sex' => $userWxInfo['sex'],
                        'wx_city' => $userWxInfo['city'],
                        'wx_province' => $userWxInfo['province'],
                        'wx_country' => $userWxInfo['country'],
                        ]);
                }
                UserManager::addUserInfo($data);
			}
		}catch(Exception $e){
			throw new UserException('userInfo.update');
		}
	}

	/**
     * 登录
     * @param  array $credentials 
     * @return               
     */
    public function login($credentials)
    {
        try{
            $user = Sentinel::authenticate($credentials, true);
            if(!$user){
                throw new UserException('admin.login');
            }
        }catch(ThrottlingException $e){
            throw new UserException('loginThroot', "登录失败次数太多，请".$e->getDelay()."s后再尝试登录");
        }
    }

    /**
     * 
     * @return 
     */
    public function logout()
    {
        $user = UserManager::getUser();
        Sentinel::logout($user, true);
    }

    /**
     * [updatePassword description]
     * @param  integer $password     
     * @param  integer $newPassword 
     * @return                
     */
    public function updatePassword($password, $newPassword)
    {
        $user = UserManager::getUser();
        if(!$user)
        {
            return redirect('admin/login');
        }
        if(!Sentinel::validateCredentials($user, ['password' => $password]))
        {
            throw new UserException('admin.password');
        }
        Sentinel::update($user, ['password' => $newPassword]);
    }

    /**
     * [isAdmin description]
     * @return boolean 
     */
    public function isAdmin()
    {
        $user = UserManager::getUser();
        if(!$user->hasAccess(['admin'])){
            throw new UserException('admin.auth');
        }
        return $user;
    }

    /**
     * 
     * @param array $userData  
     * @param array $adminData 
     * @param integer $roleId    
     */
    public function addAdmin($userData, $adminData, $roleId)
    {
        $this->isAdmin();
        try{
            DB::transaction(function() use ($userData, $adminData, $roleId) {
                $user = Sentinel::registerAndActivate($userData);
                if(!$user){
                    throw new UserException('admin.info');
                }
                $role = Sentinel::findRoleById($roleId);
                $role->users()->attach($user);
                UserManager::addAdminInfo(array_merge(['user_id' => $user->id], $adminData));
            });
        }catch(Exception $e){
            throw new UserException('admin.info');
        }
    }

    /**
     * 
     * @param  integer $userId 
     * @param  array $data   
     * @param  integer $roleId 
     * @return          
     */
    public function updateAdminInfo($userId, $data, $roleId)
    {
        DB::transaction(function() use ($userId, $data, $roleId) {
            $user = UserManager::getUserByQuery('id', $userId);
            $user->adminInfo->update($data);
            // if($user->hasAccess(['admin'])){
            //     $roleUser = RoleUser::where('user_id', $userId)->first();
            //     $roleUser->update(['role_id' => $roleId]);
            // }
        });
    }

    /**
     * 
     * @param  string $username 
     * @return            
     */
    public function deleteAdmin($username)
    {
        $loginUser = UserManager::getUser();
        $user = UserManager::getUserByQuery('username', $username);
        if($user->id == $loginUser->id){
            throw new UserException('admin.delete');
        }
        $user->delete();
    }

    /**
     * [findUserInfoWithDeviceCodeAndDeviceType description]
     * @param  string $condition  
     * @param  string $deviceType 
     * @return              
     */
    public function findUserInfoWithDeviceCodeAndDeviceType($condition, $deviceType)
    {
        $userInfoBuilder = UserManager::findUserInfoBuilederByNameOrPhone($condition);
        if(!empty($deviceType)){
            $deviceTypes = DeviceManager::findDeviceTypeBuilderByDeviceType($deviceType)->select('id', 'type')->get();
            $devices = DeviceManager::findDeviceBuilderByDeviceTypeIds($deviceTypes->pluck('id'))->select('id')->get();
            $userIds = UserManager::findUserIdByDeviceIds($devices->pluck('id'))->pluck('user_id');
            $userInfoBuilder->whereIn('user_id', $userIds);
        }
        return $userInfoBuilder->with(['devices' => function($query){
            $query->with(['deviceType' => function($query){
                $query->select('id', 'type');
            }]);
        }])->paginate(15);
    }

    /**
     * 
     * @return 
     */
    public function getAllAdminInfo()
    {
        $user = UserManager::getUser();
        $adminInfoBuilder = UserManager::getAdminInfoBuilder();
        if(!$user->hasAccess(['admin'])){
            $adminInfoBuilder->where('user_id', $user->id);
        }
        return $adminInfoBuilder->with(['user' => function($query){
            $query->with(['roles' => function($query){
                $query->select('id', 'name');
            }])->select('id', 'username');
        }])->paginate(15);
    }

    public function getUserInfo()
    {
        $user = UserManager::getUser();
        return UserManager::getUserInfoBuilderByUsername($user->username)->select(['name', 'id_number', 'phone', 'installation_address'])->first();
    }

    public function getUserInfoByQuery($column, $condition)
    {
        return UserManager::getUserInfoBuilderByColumn($column, $condition)->select(['name', 'id_number', 'phone', 'installation_address'])->first();
    }


}